<?
define("QS_SIMPLE", 0);
define("QS_ADVANCED", 1);
define("QS_EXPERT", 2);
class Search 
{
	var $DisplayMode = QS_SIMPLE;
	var $Value;
	var $Columns;
	var $DisplayLocation = QG_CONTROL_BOTTOM;
	var $Title = "";
	/**
	* JavaScript Object name for generating click events.
	* @access public
	* @var string 
	*/
	var $ObjectName;

	/**
	* Constructor
	*
	* note - Columns is passed by REFERENCE
	*/
	function Search(&$Columns, $DisplayMode = QS_SIMPLE, $ObjectName, $Title = "")
	{
		$this->Columns = &$Columns;
		$this->DisplayMode = $DisplayMode;
		$this->Title = $Title;
		$this->ObjectName = $ObjectName;
		$this->DisplayLocation = $DisplayLocation;
	}

	/**
	* Return the search part of the WHERE Clause.  Assumes all properties are correctly set and HandleEvents() has been called
	*/
	function GetQuery()
	{
		$eventoccurred = FALSE;
		switch($this->DisplayMode)
		{
			case QS_SIMPLE:
				if(!is_null($this->Value))
				{
					$terms = $this->_quotesplit($this->Value, " ");
					foreach($terms as $term){
						$out .= "/* $term */( ";
						foreach($this->Columns as $Column){
							if ($Column->Searchable)
							{
								$out .= "{$Column->DataMember} ILIKE '%{$term}%' OR ";
								$eventoccurred = TRUE;
							}
						}
						// clip the last 'OR '
						$out = substr($out, 0, strlen($out) - 3);
						$out .= ") AND ";
					}
					// clip the last 'AND '
					$out = substr($out, 0, strlen($out) - 4);
	//				echo $out;
				}
				break;
			case QS_ADVANCED:
				foreach($this->Columns as $Column)
				{
					if ( !is_null($Column->Value) && $Column->Searchable)
					{
						$terms = $this->_quotesplit($Column->Value, " ");
						$out .= "( ";
						foreach($terms as $term)
						{
							$out .= "{$Column->DataMember} ILIKE '%{$term}%' OR ";
						}
						$out = substr($out, 0, strlen($out) - 3) ;
						$out .= ") AND ";
						$eventoccurred = TRUE;
					}
				}
				// clip the last 'AND '
				$out = substr($out, 0, strlen($out) - 4);
				break;
			case QS_EXPERT:
				if (!is_null($this->Value))
				{	
					$out = $this->Value;
					$eventoccurred = TRUE;
				}
				break;
			default:
//				$this->Value = NULL;
		}
		if ($eventoccurred)
		{
			return $out;
		}
	}

	/**
	* Handles special requests that only our control would make.
	*
	* @return TRUE if something happens
	*/
	function HandleEvents($Request)
	{
		$eventoccurred = FALSE;

		if (isset($Request["ResetSearchForm"]))
		{
			$this->Value = NULL;
			if ( $this->DisplayMode == QS_ADVANCED )
			{
				foreach($this->Columns as $Column)
				{
					$this->Columns[$Column->DataMember]->Value = NULL;
				}
			}
			$eventoccurred = TRUE;
		}

		if (isset($Request["Search"]["Value"]))
		{
			$this->Value = ($Request["Search"]["Value"] != "" ? trim(stripslashes($Request["Search"]["Value"])) : NULL);
			$eventoccurred = TRUE;
		}
		
		if (isset($Request["SearchDisplayMode"]))
		{
			$this->DisplayMode = $Request["SearchDisplayMode"];
			$this->Value = NULL;
			$eventoccurred = TRUE;
		}
		
		if (is_array($Request["SearchColumn"]))
		{
			foreach($Request["SearchColumn"] as $key => $value)
			{
				$this->Columns[$key]->Value = stripslashes(trim($value)) ? $value : NULL;
				$eventoccurred = TRUE;
			}
		}
		return $eventoccurred;
	}

	/**
	* Draw the control.  Assumes all properties are correctly set and HandleEvents() has been called
	*/
	function Render()
	{
		// The Header
		$out .= "\n<!-- WARNING: The following table was generated by John Snooks' Excellent " . get_class($this) . " Class! -->\n";
		$out .= "<script type=\"text/javascript\" language=\"javascript\">function checkRet(event){if (event.keyCode == 13) document.forms['Search'].submit();}\n";
		$out .= "function AddText(column){var txtbox = document.getElementById('Search_Value'); txtbox.value = txtbox.value + ' ' + column + ' '; } </script>\n";
//		$out .= "<form id=\"Search\" action=\"\" method=\"GET\">\n";
		$out .= "<table cellpadding=\"4\" cellspacing=\"0\" border=\"0\" >\n";// width=\"100%\"

		switch($this->DisplayMode)
		{
			case QS_SIMPLE:
				$out .= "\t<tr>\n";
				$out .= "\t\t<td class=\"SearchFieldCaption\">Filter By: </td>\n";
				$out .= "\t\t<td><input name=\"Search[Value]\"  type=\"text\" value=\"{$this->Value}\"></td>\n";
				$out .= "\t</tr>\n";
				$togglebtn = "<a href=\"javascript:{$this->ObjectName}.setSearchDisplayMode(" . QS_ADVANCED . ");\">Advanced...</a> ";
				$togglebtn .= "<a href=\"javascript:{$this->ObjectName}.setSearchDisplayMode(" . QS_EXPERT . ");\">Expert...</a> ";
				break;
			case QS_ADVANCED:
				// renders a "caption: value" style form
				foreach($this->Columns as $Column)
				{
					if ($Column->Searchable == TRUE)
					{
						$out .= "\t<tr>\n";
						$out .= "\t\t<td class=\"SearchFieldCaption\">{$Column->Caption}</td>\n";
						$out .= "\t\t<td><input onKeyDown=\"checkRet(event);\" name=\"SearchColumn[{$Column->DataMember}]\"  type=\"text\" width=\"40\" value=\"{$Column->Value}\"></td>\n";
						$out .= "\t</tr>\n";
					}
				}
				$togglebtn .= "<a href=\"javascript:{$this->ObjectName}.setSearchDisplayMode(" . QS_SIMPLE . ");\">Simple...</a> ";
				break;
			case QS_EXPERT:
				$out .= "\t<tr><td colspan=\"2\">Columns:</td><tr>\n";
				$out .= "\t<tr id=\"buttons\">\n";
				$out .= "\t\t<td colspan=\"2\">\n";

				foreach($this->Columns as $Column)
				{
					if ($Column->Searchable == TRUE)
					{
						$out .= "<a href=\"#\" onclick=\"AddText('{$Column->DataMember}');\">{$Column->Caption}</a> \n";
					}
				}
				$out .= "\t\t</td>\t</tr>\n";
				$out .= "\t<tr><td colspan=\"2\" class=\"SearchFieldCaption\">Operators:</td><tr>\n";
				$out .= "\t<tr id=\"buttons\"><td colspan=\"2\" class=\"SearchFieldCaption\">";
				$out .= "<a href=\"#\" onclick=\"AddText('AND');\">AND</a> \n";
				$out .= "<a href=\"#\" onclick=\"AddText('OR');\">OR</a> \n";
				$out .= "<a href=\"#\" onclick=\"AddText('= \'Expression\'');\">Equal</a> \n";
				$out .= "<a href=\"#\" onclick=\"AddText('<> \'Expression\'');\">Not Equal</a> \n";
				$out .= "<a href=\"#\" onclick=\"AddText('ILIKE \'%Expression%\'');\">Like</a> \n";
				$out .= "<a href=\"#\" onclick=\"AddText('NOT ILIKE \'%Expression%\'');\">Not Like</a> \n";
				$out .= "<a href=\"#\" onclick=\"AddText('BETWEEN \'03/01/2001\' AND \'04/01/2001\'');\">Date Range</a> \n";
				$out .= "</td><tr>\n";
				$out .= "<tr><td colspan=\"2\"><textarea name=\"Search[Value]\" id=\"Search_Value\" cols=\"60\" rows=\"8\">{$this->Value}</textarea></td></tr>\n";
				$togglebtn .= "<a href=\"javascript:{$this->ObjectName}.setSearchDisplayMode(" . QS_SIMPLE . ");\">Simple...</a> ";
				break;
		}
		// Buttons
		$out .= "\t<tr id=\"buttons\">\n";
		$out .= "\t<td colspan=\"2\">";
		$out .= "<a href=\"javascript:{$this->ObjectName}.SubmitSearchForm();\">Search</a> ";
		$out .= "<a href=\"javascript:{$this->ObjectName}.ResetSearchForm();\">Reset</a> ";
		$out .= $togglebtn;
		$out .= "\t\t</td>\n\t</tr>";

		// The Footer
		$out .= "</table>\n";
//		$out .= "\n</form>";
		return $out;
	}

	function _quotesplit($sSearchString, $sSplitter = ',')
	{
		//First step is to split it up into the bits that are surrounded by quotes and the bits that aren't. Adding the delimiter to the ends simplifies the logic further down
		$getstrings = split('\"', $sSplitter . $sSearchString . $sSplitter);
	
		//$instring toggles so we know if we are in a quoted string or not
		$iDelimeterLength = strlen($sSplitter);
		$bInsideQuotes = FALSE;
	
		while (list($arg, $val) = each($getstrings))
		{
		   if ($bInsideQuotes)
		   {
				//Add the whole string, untouched to the $Query->FetchRow() array.
				$result[] = $val;
				$bInsideQuotes = FALSE;
		   }
		   else
		   {
				//Break up the string according to the delimiter character
				//Each string has extraneous delimiters around it (inc the ones we added above), so they need to be stripped off
			   $temparray = split($sSplitter, substr($val, $iDelimeterLength, strlen($val) - $iDelimeterLength - $iDelimeterLength ) );
		
			   while(list($iarg, $ival) = each($temparray))
			   {
					if ( trim($ival) != "" )
					{
						$result[] = trim($ival);
					}
			   }
			   $bInsideQuotes = TRUE;
		   }
	   }
	   return $result;
	}
}
?>